/*
 * Copyright 2011 LMAX Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.lmax.disruptor;


import com.lmax.disruptor.dsl.ProducerType;

/**
 * [CACHELINE] 缓存行填充基类
 * 这个抽象类通过字节填充来避免伪共享(False Sharing)问题
 * 
 * [PERFORMANCE] 性能优化原理：
 * CPU缓存行通常是64字节，如果多个线程访问的变量位于同一缓存行，
 * 会导致缓存行在CPU核心之间频繁传输，严重影响性能。
 * 通过填充56个字节(7*8字节)，确保关键字段独占一个缓存行。
 * 
 * [DESIGN] 设计模式：
 * 使用继承层次分离关注点 - 将缓存行优化与业务逻辑分离
 */
abstract class RingBufferPad
{
    // [CACHELINE] 缓存行填充字段 - 56个字节的填充，配合对象头(8字节)组成64字节
    // 这些字段仅用于占位，避免重要字段与其他对象共享缓存行
    protected byte
        p10, p11, p12, p13, p14, p15, p16, p17,  // 8字节填充
        p20, p21, p22, p23, p24, p25, p26, p27,  // 8字节填充
        p30, p31, p32, p33, p34, p35, p36, p37,  // 8字节填充
        p40, p41, p42, p43, p44, p45, p46, p47,  // 8字节填充
        p50, p51, p52, p53, p54, p55, p56, p57,  // 8字节填充
        p60, p61, p62, p63, p64, p65, p66, p67,  // 8字节填充
        p70, p71, p72, p73, p74, p75, p76, p77;  // 8字节填充，总计56字节
}

/**
 * [COMPONENT] 环形缓冲区字段抽象类
 * 包含RingBuffer的核心数据结构和字段定义
 * 
 * [DESIGN] 设计理念：
 * 继承自RingBufferPad获得缓存行对齐优化
 * 将字段定义与具体实现分离，体现单一职责原则
 * 
 * [PERFORMANCE] 性能考虑：
 * - indexMask使用位运算快速计算数组索引，避免取模运算
 * - entries数组预分配对象，避免运行时对象创建开销
 * - bufferSize必须是2的幂，支持位运算优化
 * 
 * @param <E> 存储在环形缓冲区中的事件类型
 */
abstract class RingBufferFields<E> extends RingBufferPad
{
    // [PERFORMANCE] 缓冲区填充大小 - 在数组两端添加填充，提高缓存效率
    private static final int BUFFER_PAD = 32;

    // [ALGORITHM] 索引掩码 - 用于快速计算环形数组的实际索引位置
    // 由于bufferSize是2的幂，indexMask = bufferSize - 1
    // 通过 (sequence & indexMask) 替代 (sequence % bufferSize) 提高性能
    private final long indexMask;
    
    // [RINGBUFFER] 环形缓冲区存储数组 - 预分配的事件对象数组
    // 数组大小为 bufferSize + 2 * BUFFER_PAD，两端填充提高缓存友好性
    private final E[] entries;
    
    // [COMPONENT] 缓冲区大小 - 必须是2的幂，支持位运算优化
    protected final int bufferSize;
    
    // [SEQUENCE] 序列号管理器 - 负责生产者和消费者的序列号协调
    // 通过策略模式支持单生产者和多生产者不同的实现
    protected final Sequencer sequencer;

    /**
     * [WORKFLOW] RingBufferFields构造函数
     * 初始化环形缓冲区的核心数据结构和预分配事件对象
     * 
     * [ALGORITHM] 初始化步骤：
     * 1. 验证缓冲区大小的合法性（必须>0且为2的幂）
     * 2. 计算索引掩码以支持快速位运算
     * 3. 创建带填充的事件数组
     * 4. 预填充所有事件对象
     * 
     * [PERFORMANCE] 性能考虑：
     * - 预分配所有对象避免运行时GC压力
     * - 2的幂大小支持位运算替代除法运算
     * - 数组填充提高内存访问的缓存友好性
     * 
     * @param eventFactory 事件工厂，用于创建事件实例
     * @param sequencer 序列号管理器，决定单/多生产者策略
     */
    @SuppressWarnings("unchecked")
    RingBufferFields(
        final EventFactory<E> eventFactory,
        final Sequencer sequencer)
    {
        // [COMPONENT] 设置序列号管理器，这是生产者/消费者协调的核心
        this.sequencer = sequencer;
        this.bufferSize = sequencer.getBufferSize();

        // [DESIGN] 参数验证 - 确保缓冲区大小符合设计约束
        if (bufferSize < 1)
        {
            throw new IllegalArgumentException("bufferSize must not be less than 1");
        }
        // [PERFORMANCE] 必须是2的幂，支持位运算优化
        // Integer.bitCount()返回二进制表示中1的个数，2的幂只有一个1
        if (Integer.bitCount(bufferSize) != 1)
        {
            throw new IllegalArgumentException("bufferSize must be a power of 2");
        }

        // [ALGORITHM] 计算索引掩码：bufferSize-1的二进制全为1，支持快速取模
        // 例如：bufferSize=8时，indexMask=7(111)，sequence&7 等价于 sequence%8
        this.indexMask = bufferSize - 1;
        
        // [RINGBUFFER] 创建实际存储数组，两端添加填充提高缓存性能
        this.entries = (E[]) new Object[bufferSize + 2 * BUFFER_PAD];
        
        // [PERFORMANCE] 预填充所有事件对象，避免运行时对象创建开销
        fill(eventFactory);
    }

    /**
     * [PERFORMANCE] 预填充事件对象
     * 使用事件工厂预先创建所有事件实例，避免运行时对象分配
     * 
     * [ALGORITHM] 填充策略：
     * 只填充有效的缓冲区区域，跳过前后的填充区域
     * 从BUFFER_PAD开始，填充bufferSize个事件对象
     * 
     * [DESIGN] 设计优势：
     * - 零垃圾回收：运行时不需要创建/销毁事件对象
     * - 内存预热：提前分配内存页，减少运行时页错误
     * - 对象复用：事件对象被循环复用，只需更新内容
     * 
     * @param eventFactory 事件工厂，负责创建具体的事件实例
     */
    private void fill(final EventFactory<E> eventFactory)
    {
        // [PERFORMANCE] 预填充循环：为每个有效位置创建事件对象
        for (int i = 0; i < bufferSize; i++)
        {
            // [RINGBUFFER] 从BUFFER_PAD偏移开始填充，避开前填充区域
            entries[BUFFER_PAD + i] = eventFactory.newInstance();
        }
    }

    /**
     * [ALGORITHM] 根据序列号获取对应的事件对象
     * 这是环形缓冲区的核心访问方法，通过位运算快速定位
     * 
     * [PERFORMANCE] 性能优化：
     * - 使用位运算(sequence & indexMask)替代取模运算(sequence % bufferSize)
     * - 位运算比取模运算快约10-50倍
     * - 加上BUFFER_PAD偏移跳过前填充区域
     * 
     * [CONCURRENCY] 并发安全：
     * 该方法只是读取数组元素，不涉及修改操作
     * 并发安全由序列号管理器(Sequencer)保证
     * 
     * @param sequence 事件序列号，可以是任意长整型值
     * @return 对应位置的事件对象引用
     */
    protected final E elementAt(final long sequence)
    {
        // [ALGORITHM] 核心索引计算：sequence & indexMask 实现快速环形定位
        // BUFFER_PAD偏移确保访问的是有效数据区域，不是填充区域
        return entries[BUFFER_PAD + (int) (sequence & indexMask)];
    }
}

/**
 * [ANALYSIS] Disruptor框架的核心数据结构 - 高性能环形缓冲区
 * 这是一个基于环形结构的可重用事件存储容器，支持生产者和消费者之间的高效数据交换
 * 
 * [DESIGN] 核心设计理念：
 * 设计目标：构建无锁、高吞吐、低延迟的并发数据结构
 * 核心思想：通过预分配内存、环形复用、序列号协调实现极致性能
 * 实现方式：继承层次分离关注点，接口组合定义能力边界
 * 
 * [PERFORMANCE] 性能特征：
 * 性能优势：无锁设计、零垃圾回收、缓存友好的内存布局
 * 优化手段：缓存行对齐、位运算索引、批量操作、预分配对象
 * 适用场景：高频交易、实时系统、大数据流处理等性能敏感场景
 * 
 * [CONCURRENCY] 并发安全性：
 * 线程安全：通过序列号和内存屏障保证多线程安全访问
 * 并发模型：支持多生产者/多消费者的复杂并发访问模式
 * 同步机制：基于CAS操作和等待策略的无锁同步协调
 * 
 * [PATTERN] 设计模式应用：
 * 应用模式：策略模式(等待策略)、工厂模式(事件创建)、外观模式(API封装)
 * 模式作用：提供可插拔的算法选择和简化的使用接口
 * 
 * [ARCHITECTURE] 架构层次：
 * - RingBufferPad: 缓存行对齐基类
 * - RingBufferFields: 字段定义和基础操作
 * - RingBuffer: 完整功能实现和API封装
 * 
 * [INTERFACE] 实现的核心接口：
 * - Cursored: 提供游标(序列号)访问能力
 * - EventSequencer: 提供事件序列化和发布能力
 * - EventSink: 提供事件输入和转换能力
 * 
 * 使用示例：
 * <pre>{@code
 * // 创建单生产者环形缓冲区
 * RingBuffer<MyEvent> ringBuffer = RingBuffer.createSingleProducer(
 *     MyEvent::new, 1024, new BusySpinWaitStrategy());
 * 
 * // 发布事件
 * long sequence = ringBuffer.next();
 * MyEvent event = ringBuffer.get(sequence);
 * event.setData("Hello Disruptor");
 * ringBuffer.publish(sequence);
 * }</pre>
 * 
 * @param <E> 存储在环形缓冲区中的事件类型，支持任意用户定义的事件对象
 * 
 * @author LMAX Exchange Team
 * @version 4.0.0
 * @since 1.0.0
 */
public final class RingBuffer<E> extends RingBufferFields<E> implements Cursored, EventSequencer<E>, EventSink<E>
{
    /**
     * [SEQUENCE] 初始游标值常量
     * 定义环形缓冲区游标的起始值，与Sequence.INITIAL_VALUE保持一致
     * 
     * [DESIGN] 设计意义：
     * - 提供统一的序列号起始点，确保所有组件使用相同的初始值
     * - 通常为-1，表示尚未发布任何事件
     * - 消费者可以通过检查这个值来判断是否有新事件可处理
     */
    public static final long INITIAL_CURSOR_VALUE = Sequence.INITIAL_VALUE;
    
    // [CACHELINE] RingBuffer类自身的缓存行填充字段
    // 继承了RingBufferFields的字段后，再次添加填充确保RingBuffer实例的字段不会与其他对象共享缓存行
    // 这是多层缓存行对齐策略的一部分，最大化并发性能
    protected byte
        p10, p11, p12, p13, p14, p15, p16, p17,  // 8字节填充
        p20, p21, p22, p23, p24, p25, p26, p27,  // 8字节填充
        p30, p31, p32, p33, p34, p35, p36, p37,  // 8字节填充
        p40, p41, p42, p43, p44, p45, p46, p47,  // 8字节填充
        p50, p51, p52, p53, p54, p55, p56, p57,  // 8字节填充
        p60, p61, p62, p63, p64, p65, p66, p67,  // 8字节填充
        p70, p71, p72, p73, p74, p75, p76, p77;  // 8字节填充，配合继承链实现完整的缓存行隔离

    /**
     * Construct a RingBuffer with the full option set.
     *
     * @param eventFactory to newInstance entries for filling the RingBuffer
     * @param sequencer    sequencer to handle the ordering of events moving through the RingBuffer.
     * @throws IllegalArgumentException if bufferSize is less than 1 or not a power of 2
     */
    RingBuffer(
        final EventFactory<E> eventFactory,
        final Sequencer sequencer)
    {
        super(eventFactory, sequencer);
    }

    /**
     * Create a new multiple producer RingBuffer with the specified wait strategy.
     *
     * @param <E> Class of the event stored in the ring buffer.
     * @param factory      used to create the events within the ring buffer.
     * @param bufferSize   number of elements to create within the ring buffer.
     * @param waitStrategy used to determine how to wait for new elements to become available.
     * @return a constructed ring buffer.
     * @throws IllegalArgumentException if bufferSize is less than 1 or not a power of 2
     * @see MultiProducerSequencer
     */
    public static <E> RingBuffer<E> createMultiProducer(
        final EventFactory<E> factory,
        final int bufferSize,
        final WaitStrategy waitStrategy)
    {
        MultiProducerSequencer sequencer = new MultiProducerSequencer(bufferSize, waitStrategy);

        return new RingBuffer<>(factory, sequencer);
    }

    /**
     * Create a new multiple producer RingBuffer using the default wait strategy  {@link BlockingWaitStrategy}.
     *
     * @param <E> Class of the event stored in the ring buffer.
     * @param factory    used to create the events within the ring buffer.
     * @param bufferSize number of elements to create within the ring buffer.
     * @return a constructed ring buffer.
     * @throws IllegalArgumentException if <code>bufferSize</code> is less than 1 or not a power of 2
     * @see MultiProducerSequencer
     */
    public static <E> RingBuffer<E> createMultiProducer(final EventFactory<E> factory, final int bufferSize)
    {
        return createMultiProducer(factory, bufferSize, new BlockingWaitStrategy());
    }

    /**
     * Create a new single producer RingBuffer with the specified wait strategy.
     *
     * @param <E> Class of the event stored in the ring buffer.
     * @param factory      used to create the events within the ring buffer.
     * @param bufferSize   number of elements to create within the ring buffer.
     * @param waitStrategy used to determine how to wait for new elements to become available.
     * @return a constructed ring buffer.
     * @throws IllegalArgumentException if bufferSize is less than 1 or not a power of 2
     * @see SingleProducerSequencer
     */
    public static <E> RingBuffer<E> createSingleProducer(
        final EventFactory<E> factory,
        final int bufferSize,
        final WaitStrategy waitStrategy)
    {
        SingleProducerSequencer sequencer = new SingleProducerSequencer(bufferSize, waitStrategy);

        return new RingBuffer<>(factory, sequencer);
    }

    /**
     * Create a new single producer RingBuffer using the default wait strategy  {@link BlockingWaitStrategy}.
     *
     * @param <E> Class of the event stored in the ring buffer.
     * @param factory    used to create the events within the ring buffer.
     * @param bufferSize number of elements to create within the ring buffer.
     * @return a constructed ring buffer.
     * @throws IllegalArgumentException if <code>bufferSize</code> is less than 1 or not a power of 2
     * @see MultiProducerSequencer
     */
    public static <E> RingBuffer<E> createSingleProducer(final EventFactory<E> factory, final int bufferSize)
    {
        return createSingleProducer(factory, bufferSize, new BlockingWaitStrategy());
    }

    /**
     * Create a new Ring Buffer with the specified producer type (SINGLE or MULTI)
     *
     * @param <E> Class of the event stored in the ring buffer.
     * @param producerType producer type to use {@link ProducerType}.
     * @param factory      used to create events within the ring buffer.
     * @param bufferSize   number of elements to create within the ring buffer.
     * @param waitStrategy used to determine how to wait for new elements to become available.
     * @return a constructed ring buffer.
     * @throws IllegalArgumentException if bufferSize is less than 1 or not a power of 2
     */
    public static <E> RingBuffer<E> create(
        final ProducerType producerType,
        final EventFactory<E> factory,
        final int bufferSize,
        final WaitStrategy waitStrategy)
    {
        switch (producerType)
        {
            case SINGLE:
                return createSingleProducer(factory, bufferSize, waitStrategy);
            case MULTI:
                return createMultiProducer(factory, bufferSize, waitStrategy);
            default:
                throw new IllegalStateException(producerType.toString());
        }
    }

    /**
     * <p>Get the event for a given sequence in the RingBuffer.</p>
     *
     * <p>This call has 2 uses.  Firstly use this call when publishing to a ring buffer.
     * After calling {@link RingBuffer#next()} use this call to get hold of the
     * preallocated event to fill with data before calling {@link RingBuffer#publish(long)}.</p>
     *
     * <p>Secondly use this call when consuming data from the ring buffer.  After calling
     * {@link SequenceBarrier#waitFor(long)} call this method with any value greater than
     * that your current consumer sequence and less than or equal to the value returned from
     * the {@link SequenceBarrier#waitFor(long)} method.</p>
     *
     * @param sequence for the event
     * @return the event for the given sequence
     */
    /**
     * [WORKFLOW] 根据序列号获取对应的事件对象 - 生产者和消费者访问事件的核心方法
     * 
     * [ALGORITHM] 事件获取流程：
     * 1. 调用elementAt()方法进行实际的数组访问
     * 2. 通过位运算(sequence & indexMask)快速计算数组索引
     * 3. 加上BUFFER_PAD偏移量跳过填充区域
     * 4. 返回预分配的事件对象引用
     * 
     * [PERFORMANCE] 性能特征：
     * - 时间复杂度：O(1)，固定时间访问
     * - CPU指令：仅需2-3条CPU指令完成计算
     * - 内存访问：直接数组访问，CPU缓存友好
     * - 延迟：约1-2ns，接近内存访问速度
     * 
     * [CONCURRENCY] 并发安全性：
     * - 无写操作：此方法只读取数组元素，不修改任何状态
     * - 内存可见性：依赖序列号管理器的内存屏障保证事件内容的可见性
     * - 多线程访问：生产者和消费者可以同时调用此方法访问不同位置
     * - 数据竞争：通过序列号协调避免读写冲突
     * 
     * [PATTERN] 使用场景：
     * 1. 生产者模式：next() -> get() -> 填充数据 -> publish()
     * 2. 消费者模式：waitFor() -> get() -> 处理数据 -> 更新消费进度
     * 3. 轮询模式：tryNext() -> get() -> 处理数据(可选)
     * 
     * [DESIGN] 设计优势：
     * - 零拷贝：返回的是预分配对象的引用，无需创建新对象
     * - 对象复用：同一个事件对象被循环使用，只需更新内容
     * - 类型安全：通过泛型保证类型安全，编译期检查
     * 
     * [CACHE] 缓存优化：
     * - 局部性原理：顺序访问模式有利于CPU预取和缓存命中
     * - 缓存行对齐：数组布局经过优化，减少伪共享
     * - 内存预热：预分配避免运行时的页错误
     * 
     * @param sequence 事件序列号，可以是任意长整型值
     * @return 对应位置的预分配事件对象引用，永远不会返回null
     * @see #elementAt(long) 实际的数组访问实现
     * @see #next() 序列号申请方法
     * @see #publish(long) 序列号发布方法
     */
    @Override
    public E get(final long sequence)
    {
        // [DELEGATE] 委托给elementAt()方法进行实际的数组索引计算和访问
        // 这种分层设计使得核心算法可以被子类重用
        return elementAt(sequence);
    }

    /**
     * [WORKFLOW] 申请下一个可用的序列号 - 这是生产者获取写入位置的核心方法
     * 
     * [ALGORITHM] 序列号申请流程：
     * 1. 委托给序列号管理器(Sequencer)处理具体的序列号分配逻辑
     * 2. 单生产者：简单递增本地计数器，无需原子操作
     * 3. 多生产者：使用CAS操作获取序列号，处理并发竞争
     * 4. 容量检查：确保不会覆盖未被消费的事件
     * 5. 背压处理：如果缓冲区满，会等待消费者释放空间
     * 
     * [CONCURRENCY] 并发安全保证：
     * - 单生产者模式：无并发竞争，性能最优
     * - 多生产者模式：通过原子操作保证线程安全
     * - 与消费者协调：通过序列号屏障(SequenceBarrier)确保数据安全
     * 
     * [PERFORMANCE] 性能特征：
     * - 单生产者：每次调用约2-5ns，极致性能
     * - 多生产者：每次调用约10-20ns，需要原子操作开销
     * - 背压等待：缓冲区满时会阻塞，避免数据丢失
     * 
     * [PATTERN] 使用模式：
     * 调用此方法的标准模式是try-finally结构，确保序列号一定被发布：
     * <pre>
     * long sequence = ringBuffer.next();         // 申请序列号
     * try {
     *     Event e = ringBuffer.get(sequence);    // 获取事件对象
     *     // 填充事件数据
     *     e.setData("业务数据");
     * } finally {
     *     ringBuffer.publish(sequence);          // 发布序列号，使事件对消费者可见
     * }
     * </pre>
     * 
     * [DESIGN] 设计考虑：
     * - 职责分离：RingBuffer只负责API封装，具体逻辑委托给Sequencer
     * - 策略模式：通过不同的Sequencer实现支持不同的生产者模式
     * - 异常安全：即使出现异常，也要确保序列号被正确发布
     * 
     * @return 下一个可用的序列号，保证在缓冲区有效范围内且不会覆盖未消费的事件
     * @see RingBuffer#publish(long) 发布序列号，使事件对消费者可见
     * @see RingBuffer#get(long) 根据序列号获取事件对象
     * @see Sequencer#next() 序列号管理器的具体实现
     */
    @Override
    public long next()
    {
        // [DELEGATE] 委托给序列号管理器处理具体的序列号分配逻辑
        // 这里体现了职责分离原则：RingBuffer负责API封装，Sequencer负责序列号管理
        return sequencer.next();
    }

    /**
     * The same functionality as {@link RingBuffer#next()}, but allows the caller to claim
     * the next n sequences.
     *
     * @param n number of slots to claim
     * @return sequence number of the highest slot claimed
     * @see Sequencer#next(int)
     */
    @Override
    public long next(final int n)
    {
        return sequencer.next(n);
    }

    /**
     * <p>Increment and return the next sequence for the ring buffer.  Calls of this
     * method should ensure that they always publish the sequence afterward.  E.g.</p>
     * <pre>
     * long sequence = ringBuffer.next();
     * try {
     *     Event e = ringBuffer.get(sequence);
     *     // Do some work with the event.
     * } finally {
     *     ringBuffer.publish(sequence);
     * }
     * </pre>
     * <p>This method will not block if there is not space available in the ring
     * buffer, instead it will throw an {@link InsufficientCapacityException}.</p>
     *
     * @return The next sequence to publish to.
     * @throws InsufficientCapacityException if the necessary space in the ring buffer is not available
     * @see RingBuffer#publish(long)
     * @see RingBuffer#get(long)
     */
    @Override
    public long tryNext() throws InsufficientCapacityException
    {
        return sequencer.tryNext();
    }

    /**
     * The same functionality as {@link RingBuffer#tryNext()}, but allows the caller to attempt
     * to claim the next n sequences.
     *
     * @param n number of slots to claim
     * @return sequence number of the highest slot claimed
     * @throws InsufficientCapacityException if the necessary space in the ring buffer is not available
     */
    @Override
    public long tryNext(final int n) throws InsufficientCapacityException
    {
        return sequencer.tryNext(n);
    }

    /**
     * Sets the cursor to a specific sequence and returns the preallocated entry that is stored there.  This
     * can cause a data race and should only be done in controlled circumstances, e.g. during initialisation.
     *
     * @param sequence The sequence to claim.
     * @return The preallocated event.
     */
    public E claimAndGetPreallocated(final long sequence)
    {
        sequencer.claim(sequence);
        return get(sequence);
    }

    /**
     * Determines if the event for a given sequence is currently available.
     *
     * <p>Note that this does not guarantee that event will still be available
     * on the next interaction with the RingBuffer. For example, it is not
     * necessarily safe to write code like this:
     *
     * <pre>{@code
     * if (ringBuffer.isAvailable(sequence))
     * {
     *     final E e = ringBuffer.get(sequence);
     *     // ...do something with e
     * }
     * }</pre>
     *
     * <p>because there is a race between the reading thread and the writing thread.
     *
     * <p>This method will also return false when querying for sequences that are
     * behind the ring buffer's wrap point.
     *
     * @param sequence The sequence to identify the entry.
     * @return If the event published with the given sequence number is currently available.
     */
    public boolean isAvailable(final long sequence)
    {
        return sequencer.isAvailable(sequence);
    }

    /**
     * Add the specified gating sequences to this instance of the Disruptor.  They will
     * safely and atomically added to the list of gating sequences.
     *
     * @param gatingSequences The sequences to add.
     */
    public void addGatingSequences(final Sequence... gatingSequences)
    {
        sequencer.addGatingSequences(gatingSequences);
    }

    /**
     * Get the minimum sequence value from all of the gating sequences
     * added to this ringBuffer.
     *
     * @return The minimum gating sequence or the cursor sequence if
     * no sequences have been added.
     */
    public long getMinimumGatingSequence()
    {
        return sequencer.getMinimumSequence();
    }

    /**
     * Remove the specified sequence from this ringBuffer.
     *
     * @param sequence to be removed.
     * @return <code>true</code> if this sequence was found, <code>false</code> otherwise.
     */
    public boolean removeGatingSequence(final Sequence sequence)
    {
        return sequencer.removeGatingSequence(sequence);
    }

    /**
     * Create a new SequenceBarrier to be used by an EventProcessor to track which messages
     * are available to be read from the ring buffer given a list of sequences to track.
     *
     * @param sequencesToTrack the additional sequences to track
     * @return A sequence barrier that will track the specified sequences.
     * @see SequenceBarrier
     */
    public SequenceBarrier newBarrier(final Sequence... sequencesToTrack)
    {
        return sequencer.newBarrier(sequencesToTrack);
    }

    /**
     * Creates an event poller for this ring buffer gated on the supplied sequences.
     *
     * @param gatingSequences to be gated on.
     * @return A poller that will gate on this ring buffer and the supplied sequences.
     */
    public EventPoller<E> newPoller(final Sequence... gatingSequences)
    {
        return sequencer.newPoller(this, gatingSequences);
    }

    /**
     * Get the current cursor value for the ring buffer.  The actual value received
     * will depend on the type of {@link Sequencer} that is being used.
     *
     * @see MultiProducerSequencer
     * @see SingleProducerSequencer
     */
    @Override
    public long getCursor()
    {
        return sequencer.getCursor();
    }

    /**
     * The size of the buffer.
     *
     * @return size of buffer
     */
    @Override
    public int getBufferSize()
    {
        return bufferSize;
    }

    /**
     * Given specified <code>requiredCapacity</code> determines if that amount of space
     * is available.  Note, you can not assume that if this method returns <code>true</code>
     * that a call to {@link RingBuffer#next()} will not block.  Especially true if this
     * ring buffer is set up to handle multiple producers.
     *
     * @param requiredCapacity The capacity to check for.
     * @return <code>true</code> If the specified <code>requiredCapacity</code> is available
     * <code>false</code> if not.
     */
    @Override
    public boolean hasAvailableCapacity(final int requiredCapacity)
    {
        return sequencer.hasAvailableCapacity(requiredCapacity);
    }


    /**
     * @see com.lmax.disruptor.EventSink#publishEvent(com.lmax.disruptor.EventTranslator)
     */
    @Override
    public void publishEvent(final EventTranslator<E> translator)
    {
        final long sequence = sequencer.next();
        translateAndPublish(translator, sequence);
    }

    /**
     * @see com.lmax.disruptor.EventSink#tryPublishEvent(com.lmax.disruptor.EventTranslator)
     */
    @Override
    public boolean tryPublishEvent(final EventTranslator<E> translator)
    {
        try
        {
            final long sequence = sequencer.tryNext();
            translateAndPublish(translator, sequence);
            return true;
        }
        catch (InsufficientCapacityException e)
        {
            return false;
        }
    }

    /**
     * @see com.lmax.disruptor.EventSink#publishEvent(com.lmax.disruptor.EventTranslatorOneArg, Object)
     * com.lmax.disruptor.EventSink#publishEvent(com.lmax.disruptor.EventTranslatorOneArg, A)
     */
    @Override
    public <A> void publishEvent(final EventTranslatorOneArg<E, A> translator, final A arg0)
    {
        final long sequence = sequencer.next();
        translateAndPublish(translator, sequence, arg0);
    }

    /**
     * @see com.lmax.disruptor.EventSink#tryPublishEvent(com.lmax.disruptor.EventTranslatorOneArg, Object)
     * com.lmax.disruptor.EventSink#tryPublishEvent(com.lmax.disruptor.EventTranslatorOneArg, A)
     */
    @Override
    public <A> boolean tryPublishEvent(final EventTranslatorOneArg<E, A> translator, final A arg0)
    {
        try
        {
            final long sequence = sequencer.tryNext();
            translateAndPublish(translator, sequence, arg0);
            return true;
        }
        catch (InsufficientCapacityException e)
        {
            return false;
        }
    }

    /**
     * @see com.lmax.disruptor.EventSink#publishEvent(com.lmax.disruptor.EventTranslatorTwoArg, Object, Object)
     * com.lmax.disruptor.EventSink#publishEvent(com.lmax.disruptor.EventTranslatorTwoArg, A, B)
     */
    @Override
    public <A, B> void publishEvent(final EventTranslatorTwoArg<E, A, B> translator, final A arg0, final B arg1)
    {
        final long sequence = sequencer.next();
        translateAndPublish(translator, sequence, arg0, arg1);
    }

    /**
     * @see com.lmax.disruptor.EventSink#tryPublishEvent(com.lmax.disruptor.EventTranslatorTwoArg, Object, Object)
     * com.lmax.disruptor.EventSink#tryPublishEvent(com.lmax.disruptor.EventTranslatorTwoArg, A, B)
     */
    @Override
    public <A, B> boolean tryPublishEvent(final EventTranslatorTwoArg<E, A, B> translator, final A arg0, final B arg1)
    {
        try
        {
            final long sequence = sequencer.tryNext();
            translateAndPublish(translator, sequence, arg0, arg1);
            return true;
        }
        catch (InsufficientCapacityException e)
        {
            return false;
        }
    }

    /**
     * @see com.lmax.disruptor.EventSink#publishEvent(com.lmax.disruptor.EventTranslatorThreeArg, Object, Object, Object)
     * com.lmax.disruptor.EventSink#publishEvent(com.lmax.disruptor.EventTranslatorThreeArg, A, B, C)
     */
    @Override
    public <A, B, C> void publishEvent(final EventTranslatorThreeArg<E, A, B, C> translator, final A arg0, final B arg1, final C arg2)
    {
        final long sequence = sequencer.next();
        translateAndPublish(translator, sequence, arg0, arg1, arg2);
    }

    /**
     * @see com.lmax.disruptor.EventSink#tryPublishEvent(com.lmax.disruptor.EventTranslatorThreeArg, Object, Object, Object)
     * com.lmax.disruptor.EventSink#tryPublishEvent(com.lmax.disruptor.EventTranslatorThreeArg, A, B, C)
     */
    @Override
    public <A, B, C> boolean tryPublishEvent(final EventTranslatorThreeArg<E, A, B, C> translator, final A arg0, final B arg1, final C arg2)
    {
        try
        {
            final long sequence = sequencer.tryNext();
            translateAndPublish(translator, sequence, arg0, arg1, arg2);
            return true;
        }
        catch (InsufficientCapacityException e)
        {
            return false;
        }
    }

    /**
     * @see com.lmax.disruptor.EventSink#publishEvent(com.lmax.disruptor.EventTranslatorVararg, java.lang.Object...)
     */
    @Override
    public void publishEvent(final EventTranslatorVararg<E> translator, final Object... args)
    {
        final long sequence = sequencer.next();
        translateAndPublish(translator, sequence, args);
    }

    /**
     * @see com.lmax.disruptor.EventSink#tryPublishEvent(com.lmax.disruptor.EventTranslatorVararg, java.lang.Object...)
     */
    @Override
    public boolean tryPublishEvent(final EventTranslatorVararg<E> translator, final Object... args)
    {
        try
        {
            final long sequence = sequencer.tryNext();
            translateAndPublish(translator, sequence, args);
            return true;
        }
        catch (InsufficientCapacityException e)
        {
            return false;
        }
    }


    /**
     * @see com.lmax.disruptor.EventSink#publishEvents(com.lmax.disruptor.EventTranslator[])
     */
    @Override
    public void publishEvents(final EventTranslator<E>[] translators)
    {
        publishEvents(translators, 0, translators.length);
    }

    /**
     * @see com.lmax.disruptor.EventSink#publishEvents(com.lmax.disruptor.EventTranslator[], int, int)
     */
    @Override
    public void publishEvents(final EventTranslator<E>[] translators, final int batchStartsAt, final int batchSize)
    {
        checkBounds(translators, batchStartsAt, batchSize);
        final long finalSequence = sequencer.next(batchSize);
        translateAndPublishBatch(translators, batchStartsAt, batchSize, finalSequence);
    }

    /**
     * @see com.lmax.disruptor.EventSink#tryPublishEvents(com.lmax.disruptor.EventTranslator[])
     */
    @Override
    public boolean tryPublishEvents(final EventTranslator<E>[] translators)
    {
        return tryPublishEvents(translators, 0, translators.length);
    }

    /**
     * @see com.lmax.disruptor.EventSink#tryPublishEvents(com.lmax.disruptor.EventTranslator[], int, int)
     */
    @Override
    public boolean tryPublishEvents(final EventTranslator<E>[] translators, final int batchStartsAt, final int batchSize)
    {
        checkBounds(translators, batchStartsAt, batchSize);
        try
        {
            final long finalSequence = sequencer.tryNext(batchSize);
            translateAndPublishBatch(translators, batchStartsAt, batchSize, finalSequence);
            return true;
        }
        catch (InsufficientCapacityException e)
        {
            return false;
        }
    }

    /**
     * @see com.lmax.disruptor.EventSink#publishEvents(com.lmax.disruptor.EventTranslatorOneArg, Object[])
     * com.lmax.disruptor.EventSink#publishEvents(com.lmax.disruptor.EventTranslatorOneArg, A[])
     */
    @Override
    public <A> void publishEvents(final EventTranslatorOneArg<E, A> translator, final A[] arg0)
    {
        publishEvents(translator, 0, arg0.length, arg0);
    }

    /**
     * @see com.lmax.disruptor.EventSink#publishEvents(com.lmax.disruptor.EventTranslatorOneArg, int, int, Object[])
     * com.lmax.disruptor.EventSink#publishEvents(com.lmax.disruptor.EventTranslatorOneArg, int, int, A[])
     */
    @Override
    public <A> void publishEvents(final EventTranslatorOneArg<E, A> translator, final int batchStartsAt, final int batchSize, final A[] arg0)
    {
        checkBounds(arg0, batchStartsAt, batchSize);
        final long finalSequence = sequencer.next(batchSize);
        translateAndPublishBatch(translator, arg0, batchStartsAt, batchSize, finalSequence);
    }

    /**
     * @see com.lmax.disruptor.EventSink#tryPublishEvents(com.lmax.disruptor.EventTranslatorOneArg, Object[])
     * com.lmax.disruptor.EventSink#tryPublishEvents(com.lmax.disruptor.EventTranslatorOneArg, A[])
     */
    @Override
    public <A> boolean tryPublishEvents(final EventTranslatorOneArg<E, A> translator, final A[] arg0)
    {
        return tryPublishEvents(translator, 0, arg0.length, arg0);
    }

    /**
     * @see com.lmax.disruptor.EventSink#tryPublishEvents(com.lmax.disruptor.EventTranslatorOneArg, int, int, Object[])
     * com.lmax.disruptor.EventSink#tryPublishEvents(com.lmax.disruptor.EventTranslatorOneArg, int, int, A[])
     */
    @Override
    public <A> boolean tryPublishEvents(
            final EventTranslatorOneArg<E, A> translator, final int batchStartsAt, final int batchSize, final A[] arg0)
    {
        checkBounds(arg0, batchStartsAt, batchSize);
        try
        {
            final long finalSequence = sequencer.tryNext(batchSize);
            translateAndPublishBatch(translator, arg0, batchStartsAt, batchSize, finalSequence);
            return true;
        }
        catch (InsufficientCapacityException e)
        {
            return false;
        }
    }

    /**
     * @see com.lmax.disruptor.EventSink#publishEvents(com.lmax.disruptor.EventTranslatorTwoArg, Object[], Object[])
     * com.lmax.disruptor.EventSink#publishEvents(com.lmax.disruptor.EventTranslatorTwoArg, A[], B[])
     */
    @Override
    public <A, B> void publishEvents(final EventTranslatorTwoArg<E, A, B> translator, final A[] arg0, final B[] arg1)
    {
        publishEvents(translator, 0, arg0.length, arg0, arg1);
    }

    /**
     * @see com.lmax.disruptor.EventSink#publishEvents(com.lmax.disruptor.EventTranslatorTwoArg, int, int, Object[], Object[])
     * com.lmax.disruptor.EventSink#publishEvents(com.lmax.disruptor.EventTranslatorTwoArg, int, int, A[], B[])
     */
    @Override
    public <A, B> void publishEvents(
        final EventTranslatorTwoArg<E, A, B> translator, final int batchStartsAt, final int batchSize, final A[] arg0, final B[] arg1)
    {
        checkBounds(arg0, arg1, batchStartsAt, batchSize);
        final long finalSequence = sequencer.next(batchSize);
        translateAndPublishBatch(translator, arg0, arg1, batchStartsAt, batchSize, finalSequence);
    }

    /**
     * @see com.lmax.disruptor.EventSink#tryPublishEvents(com.lmax.disruptor.EventTranslatorTwoArg, Object[], Object[])
     * com.lmax.disruptor.EventSink#tryPublishEvents(com.lmax.disruptor.EventTranslatorTwoArg, A[], B[])
     */
    @Override
    public <A, B> boolean tryPublishEvents(final EventTranslatorTwoArg<E, A, B> translator, final A[] arg0, final B[] arg1)
    {
        return tryPublishEvents(translator, 0, arg0.length, arg0, arg1);
    }

    /**
     * @see com.lmax.disruptor.EventSink#tryPublishEvents(com.lmax.disruptor.EventTranslatorTwoArg, int, int, Object[], Object[])
     * com.lmax.disruptor.EventSink#tryPublishEvents(com.lmax.disruptor.EventTranslatorTwoArg, int, int, A[], B[])
     */
    @Override
    public <A, B> boolean tryPublishEvents(
        final EventTranslatorTwoArg<E, A, B> translator, final int batchStartsAt, final int batchSize, final A[] arg0, final B[] arg1)
    {
        checkBounds(arg0, arg1, batchStartsAt, batchSize);
        try
        {
            final long finalSequence = sequencer.tryNext(batchSize);
            translateAndPublishBatch(translator, arg0, arg1, batchStartsAt, batchSize, finalSequence);
            return true;
        }
        catch (InsufficientCapacityException e)
        {
            return false;
        }
    }

    /**
     * @see com.lmax.disruptor.EventSink#publishEvents(com.lmax.disruptor.EventTranslatorThreeArg, Object[], Object[], Object[])
     * com.lmax.disruptor.EventSink#publishEvents(com.lmax.disruptor.EventTranslatorThreeArg, A[], B[], C[])
     */
    @Override
    public <A, B, C> void publishEvents(final EventTranslatorThreeArg<E, A, B, C> translator, final A[] arg0, final B[] arg1, final C[] arg2)
    {
        publishEvents(translator, 0, arg0.length, arg0, arg1, arg2);
    }

    /**
     * @see com.lmax.disruptor.EventSink#publishEvents(com.lmax.disruptor.EventTranslatorThreeArg, int, int, Object[], Object[], Object[])
     * com.lmax.disruptor.EventSink#publishEvents(com.lmax.disruptor.EventTranslatorThreeArg, int, int, A[], B[], C[])
     */
    @Override
    public <A, B, C> void publishEvents(
        final EventTranslatorThreeArg<E, A, B, C> translator, final int batchStartsAt, final int batchSize, final A[] arg0, final B[] arg1, final C[] arg2)
    {
        checkBounds(arg0, arg1, arg2, batchStartsAt, batchSize);
        final long finalSequence = sequencer.next(batchSize);
        translateAndPublishBatch(translator, arg0, arg1, arg2, batchStartsAt, batchSize, finalSequence);
    }

    /**
     * @see com.lmax.disruptor.EventSink#tryPublishEvents(com.lmax.disruptor.EventTranslatorThreeArg, Object[], Object[], Object[])
     * com.lmax.disruptor.EventSink#tryPublishEvents(com.lmax.disruptor.EventTranslatorThreeArg, A[], B[], C[])
     */
    @Override
    public <A, B, C> boolean tryPublishEvents(
        final EventTranslatorThreeArg<E, A, B, C> translator, final A[] arg0, final B[] arg1, final C[] arg2)
    {
        return tryPublishEvents(translator, 0, arg0.length, arg0, arg1, arg2);
    }

    /**
     * @see com.lmax.disruptor.EventSink#tryPublishEvents(com.lmax.disruptor.EventTranslatorThreeArg, int, int, Object[], Object[], Object[])
     * com.lmax.disruptor.EventSink#tryPublishEvents(com.lmax.disruptor.EventTranslatorThreeArg, int, int, A[], B[], C[])
     */
    @Override
    public <A, B, C> boolean tryPublishEvents(
        final EventTranslatorThreeArg<E, A, B, C> translator, final int batchStartsAt, final int batchSize, final A[] arg0, final B[] arg1, final C[] arg2)
    {
        checkBounds(arg0, arg1, arg2, batchStartsAt, batchSize);
        try
        {
            final long finalSequence = sequencer.tryNext(batchSize);
            translateAndPublishBatch(translator, arg0, arg1, arg2, batchStartsAt, batchSize, finalSequence);
            return true;
        }
        catch (InsufficientCapacityException e)
        {
            return false;
        }
    }

    /**
     * @see com.lmax.disruptor.EventSink#publishEvents(com.lmax.disruptor.EventTranslatorVararg, java.lang.Object[][])
     */
    @Override
    public void publishEvents(final EventTranslatorVararg<E> translator, final Object[]... args)
    {
        publishEvents(translator, 0, args.length, args);
    }

    /**
     * @see com.lmax.disruptor.EventSink#publishEvents(com.lmax.disruptor.EventTranslatorVararg, int, int, java.lang.Object[][])
     */
    @Override
    public void publishEvents(final EventTranslatorVararg<E> translator, final int batchStartsAt, final int batchSize, final Object[]... args)
    {
        checkBounds(batchStartsAt, batchSize, args);
        final long finalSequence = sequencer.next(batchSize);
        translateAndPublishBatch(translator, batchStartsAt, batchSize, finalSequence, args);
    }

    /**
     * @see com.lmax.disruptor.EventSink#tryPublishEvents(com.lmax.disruptor.EventTranslatorVararg, java.lang.Object[][])
     */
    @Override
    public boolean tryPublishEvents(final EventTranslatorVararg<E> translator, final Object[]... args)
    {
        return tryPublishEvents(translator, 0, args.length, args);
    }

    /**
     * @see com.lmax.disruptor.EventSink#tryPublishEvents(com.lmax.disruptor.EventTranslatorVararg, int, int, java.lang.Object[][])
     */
    @Override
    public boolean tryPublishEvents(
        final EventTranslatorVararg<E> translator, final int batchStartsAt, final int batchSize, final Object[]... args)
    {
        checkBounds(args, batchStartsAt, batchSize);
        try
        {
            final long finalSequence = sequencer.tryNext(batchSize);
            translateAndPublishBatch(translator, batchStartsAt, batchSize, finalSequence, args);
            return true;
        }
        catch (InsufficientCapacityException e)
        {
            return false;
        }
    }

    /**
     * Publish the specified sequence.  This action marks this particular
     * message as being available to be read.
     *
     * @param sequence the sequence to publish.
     */
    /**
     * [WORKFLOW] 发布序列号，使事件对消费者可见 - 生产者完成事件发布的关键步骤
     * 
     * [ALGORITHM] 序列号发布流程：
     * 1. 委托给序列号管理器(Sequencer)执行具体的发布逻辑
     * 2. 单生产者：直接更新cursor序列号，通过volatile写保证可见性
     * 3. 多生产者：标记availableBuffer中的对应位置，处理乱序发布
     * 4. 内存屏障：确保事件数据的写入在序列号发布之前完成
     * 5. 唤醒消费者：通知等待策略唤醒阻塞的消费者线程
     * 
     * [CONCURRENCY] 并发安全保证：
     * - 内存屏障：通过volatile写或VarHandle的release语义确保写入顺序
     * - 原子性：序列号的发布是原子操作，保证一致性状态
     * - 可见性：发布后立即对所有消费者线程可见
     * - 顺序性：确保事件数据的修改在序列号发布之前对其他线程可见
     * 
     * [PERFORMANCE] 性能特征：
     * - 单生产者：volatile写操作，约2-5ns
     * - 多生产者：可能需要等待前序序列号发布，延迟不确定
     * - 内存屏障：StoreStore屏障确保写入顺序，约1-2ns开销
     * - 批量发布：支持批量发布多个序列号，提高吞吐量
     * 
     * [MEMORY_MODEL] 内存模型语义：
     * - Happens-Before关系：事件数据修改 -> 序列号发布 -> 消费者读取
     * - Release语义：发布操作具有release语义，之前的写入对后续读取可见
     * - 内存同步：与消费者的acquire操作形成同步关系
     * 
     * [DESIGN] 设计考虑：
     * - 职责分离：RingBuffer负责API，Sequencer负责具体的并发控制
     * - 异常安全：必须在finally块中调用，确保序列号一定被发布
     * - 批量优化：支持发布序列号范围，提高批处理效率
     * 
     * [WAITSTRATEGY] 等待策略协调：
     * - BlockingWaitStrategy：通过锁和条件变量唤醒等待的消费者
     * - YieldingWaitStrategy：通过Thread.yield()让出CPU时间片
     * - BusySpinWaitStrategy：消费者忙等待，此方法无需特殊处理
     * - SleepingWaitStrategy：通过LockSupport.unpark()唤醒消费者
     * 
     * @param sequence 要发布的序列号，必须是之前通过next()方法获得的序列号
     * @see #next() 序列号申请方法
     * @see #get(long) 事件获取方法
     * @see Sequencer#publish(long) 序列号管理器的具体实现
     */
    @Override
    public void publish(final long sequence)
    {
        // [DELEGATE] 委托给序列号管理器处理具体的发布逻辑和内存屏障控制
        // 这里体现了策略模式：不同的Sequencer实现有不同的发布策略
        sequencer.publish(sequence);
    }

    /**
     * Publish the specified sequences.  This action marks these particular
     * messages as being available to be read.
     *
     * @param lo the lowest sequence number to be published
     * @param hi the highest sequence number to be published
     * @see Sequencer#next(int)
     */
    @Override
    public void publish(final long lo, final long hi)
    {
        sequencer.publish(lo, hi);
    }

    /**
     * Get the remaining capacity for this ringBuffer.
     *
     * @return The number of slots remaining.
     */
    @Override
    public long remainingCapacity()
    {
        return sequencer.remainingCapacity();
    }

    private void checkBounds(final EventTranslator<E>[] translators, final int batchStartsAt, final int batchSize)
    {
        checkBatchSizing(batchStartsAt, batchSize);
        batchOverRuns(translators, batchStartsAt, batchSize);
    }

    private void checkBatchSizing(final int batchStartsAt, final int batchSize)
    {
        if (batchStartsAt < 0 || batchSize < 0)
        {
            throw new IllegalArgumentException("Both batchStartsAt and batchSize must be positive but got: batchStartsAt " + batchStartsAt + " and batchSize " + batchSize);
        }
        else if (batchSize > bufferSize)
        {
            throw new IllegalArgumentException("The ring buffer cannot accommodate " + batchSize + " it only has space for " + bufferSize + " entities.");
        }
    }

    private <A> void checkBounds(final A[] arg0, final int batchStartsAt, final int batchSize)
    {
        checkBatchSizing(batchStartsAt, batchSize);
        batchOverRuns(arg0, batchStartsAt, batchSize);
    }

    private <A, B> void checkBounds(final A[] arg0, final B[] arg1, final int batchStartsAt, final int batchSize)
    {
        checkBatchSizing(batchStartsAt, batchSize);
        batchOverRuns(arg0, batchStartsAt, batchSize);
        batchOverRuns(arg1, batchStartsAt, batchSize);
    }

    private <A, B, C> void checkBounds(
        final A[] arg0, final B[] arg1, final C[] arg2, final int batchStartsAt, final int batchSize)
    {
        checkBatchSizing(batchStartsAt, batchSize);
        batchOverRuns(arg0, batchStartsAt, batchSize);
        batchOverRuns(arg1, batchStartsAt, batchSize);
        batchOverRuns(arg2, batchStartsAt, batchSize);
    }

    private void checkBounds(final int batchStartsAt, final int batchSize, final Object[][] args)
    {
        checkBatchSizing(batchStartsAt, batchSize);
        batchOverRuns(args, batchStartsAt, batchSize);
    }

    private <A> void batchOverRuns(final A[] arg0, final int batchStartsAt, final int batchSize)
    {
        if (batchStartsAt + batchSize > arg0.length)
        {
            throw new IllegalArgumentException(
                "A batchSize of: " + batchSize +
                    " with batchStatsAt of: " + batchStartsAt +
                    " will overrun the available number of arguments: " + (arg0.length - batchStartsAt));
        }
    }

    private void translateAndPublish(final EventTranslator<E> translator, final long sequence)
    {
        try
        {
            translator.translateTo(get(sequence), sequence);
        }
        finally
        {
            sequencer.publish(sequence);
        }
    }

    private <A> void translateAndPublish(final EventTranslatorOneArg<E, A> translator, final long sequence, final A arg0)
    {
        try
        {
            translator.translateTo(get(sequence), sequence, arg0);
        }
        finally
        {
            sequencer.publish(sequence);
        }
    }

    private <A, B> void translateAndPublish(final EventTranslatorTwoArg<E, A, B> translator, final long sequence, final A arg0, final B arg1)
    {
        try
        {
            translator.translateTo(get(sequence), sequence, arg0, arg1);
        }
        finally
        {
            sequencer.publish(sequence);
        }
    }

    private <A, B, C> void translateAndPublish(
        final EventTranslatorThreeArg<E, A, B, C> translator, final long sequence,
        final A arg0, final B arg1, final C arg2)
    {
        try
        {
            translator.translateTo(get(sequence), sequence, arg0, arg1, arg2);
        }
        finally
        {
            sequencer.publish(sequence);
        }
    }

    private void translateAndPublish(final EventTranslatorVararg<E> translator, final long sequence, final Object... args)
    {
        try
        {
            translator.translateTo(get(sequence), sequence, args);
        }
        finally
        {
            sequencer.publish(sequence);
        }
    }

    private void translateAndPublishBatch(
        final EventTranslator<E>[] translators, final int batchStartsAt,
        final int batchSize, final long finalSequence)
    {
        final long initialSequence = finalSequence - (batchSize - 1);
        try
        {
            long sequence = initialSequence;
            final int batchEndsAt = batchStartsAt + batchSize;
            for (int i = batchStartsAt; i < batchEndsAt; i++)
            {
                final EventTranslator<E> translator = translators[i];
                translator.translateTo(get(sequence), sequence++);
            }
        }
        finally
        {
            sequencer.publish(initialSequence, finalSequence);
        }
    }

    private <A> void translateAndPublishBatch(
        final EventTranslatorOneArg<E, A> translator, final A[] arg0,
        final int batchStartsAt, final int batchSize, final long finalSequence)
    {
        final long initialSequence = finalSequence - (batchSize - 1);
        try
        {
            long sequence = initialSequence;
            final int batchEndsAt = batchStartsAt + batchSize;
            for (int i = batchStartsAt; i < batchEndsAt; i++)
            {
                translator.translateTo(get(sequence), sequence++, arg0[i]);
            }
        }
        finally
        {
            sequencer.publish(initialSequence, finalSequence);
        }
    }

    private <A, B> void translateAndPublishBatch(
        final EventTranslatorTwoArg<E, A, B> translator, final A[] arg0,
        final B[] arg1, final int batchStartsAt, final int batchSize,
        final long finalSequence)
    {
        final long initialSequence = finalSequence - (batchSize - 1);
        try
        {
            long sequence = initialSequence;
            final int batchEndsAt = batchStartsAt + batchSize;
            for (int i = batchStartsAt; i < batchEndsAt; i++)
            {
                translator.translateTo(get(sequence), sequence++, arg0[i], arg1[i]);
            }
        }
        finally
        {
            sequencer.publish(initialSequence, finalSequence);
        }
    }

    private <A, B, C> void translateAndPublishBatch(
        final EventTranslatorThreeArg<E, A, B, C> translator,
        final A[] arg0, final B[] arg1, final C[] arg2, final int batchStartsAt,
        final int batchSize, final long finalSequence)
    {
        final long initialSequence = finalSequence - (batchSize - 1);
        try
        {
            long sequence = initialSequence;
            final int batchEndsAt = batchStartsAt + batchSize;
            for (int i = batchStartsAt; i < batchEndsAt; i++)
            {
                translator.translateTo(get(sequence), sequence++, arg0[i], arg1[i], arg2[i]);
            }
        }
        finally
        {
            sequencer.publish(initialSequence, finalSequence);
        }
    }

    private void translateAndPublishBatch(
        final EventTranslatorVararg<E> translator, final int batchStartsAt,
        final int batchSize, final long finalSequence, final Object[][] args)
    {
        final long initialSequence = finalSequence - (batchSize - 1);
        try
        {
            long sequence = initialSequence;
            final int batchEndsAt = batchStartsAt + batchSize;
            for (int i = batchStartsAt; i < batchEndsAt; i++)
            {
                translator.translateTo(get(sequence), sequence++, args[i]);
            }
        }
        finally
        {
            sequencer.publish(initialSequence, finalSequence);
        }
    }

    @Override
    public String toString()
    {
        return "RingBuffer{" +
            "bufferSize=" + bufferSize +
            ", sequencer=" + sequencer +
            "}";
    }
}
